import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 加减法口算练习系统-v0.3（含内置自动化测试）
 * 核心功能：无重复算式、加减法比例可控、带答案、合规约束、多行对齐
 * 新增：内置测试函数，自动验证所有核心需求，输出测试报告
 */
public class CalculationSystemV03 {
    // 核心配置常量（可按需调整）
    private static final int TOTAL_QUESTIONS = 50;    // 总题数
    private static final int QUESTIONS_PER_LINE = 3;  // 每行显示题数
    private static final int NUM_MAX = 99;            // 数字最大值（100以内）
    private static final int SUM_UPPER_LIMIT = 100;   // 加法和上限
    private static final int DIFF_LOWER_LIMIT = 0;    // 减法差下限
    private static final int ADD_RATIO = 60;          // 加法占比（百分比）
    private static final boolean ENABLE_TEST = true;  // 测试开关（true=执行测试，false=仅输出习题）

    // 计算目标题数
    private static final int ADD_COUNT = TOTAL_QUESTIONS * ADD_RATIO / 100;
    private static final int SUB_COUNT = TOTAL_QUESTIONS - ADD_COUNT;

    // 存储核心数据（供测试函数访问）
    private static Set<String> usedExpressions;  // 已用核心算式（去重）
    private static List<String> allQuestions;    // 完整算式列表（含答案）

    public static void main(String[] args) {
        // 打印系统标题
        System.out.println("==================== 加减法口算练习系统-v0.3 ====================");
        System.out.println("核心功能：100以内加减法+答案、无重复算式、加减法比例可控（当前加法" + ADD_RATIO + "%）");
        System.out.println("===============================================================");

        // 初始化数据结构
        Random random = new Random();
        usedExpressions = new HashSet<>();
        allQuestions = new ArrayList<>();

        // 生成题目（无重复+比例可控）
        generateAddQuestions(random);
        generateSubQuestions(random);
        Collections.shuffle(allQuestions, random);

        // 执行内置自动化测试（若开关开启）
        if (ENABLE_TEST) {
            System.out.println("[自动测试启动] 正在验证核心功能...");
            boolean testPassed = runAllTests();  // 执行所有测试用例
            System.out.println("===============================================================");
            if (testPassed) {
                System.out.println("[测试结果] 所有核心需求验证通过！");
            } else {
                System.out.println("[测试结果] 部分需求未满足，请检查程序或配置！");
            }
            System.out.println("===============================================================");
        }

        // 输出习题（排版对齐）
        printQuestions();

        System.out.println("===============================================================");
        System.out.println("练习结束！可对照答案自查～");
    }

    /**
     * 生成无重复加法算式
     */
    private static void generateAddQuestions(Random random) {
        int count = 0;
        while (count < ADD_COUNT) {
            int num1 = random.nextInt(NUM_MAX + 1);
            int num2 = random.nextInt(SUM_UPPER_LIMIT - num1 + 1);
            int answer = num1 + num2;
            String coreExpr = num1 + "+" + num2;

            if (!usedExpressions.contains(coreExpr)) {
                usedExpressions.add(coreExpr);
                String fullExpr = String.format("%2d + %2d = %2d", num1, num2, answer);
                allQuestions.add(fullExpr);
                count++;
            }
        }
    }

    /**
     * 生成无重复减法算式
     */
    private static void generateSubQuestions(Random random) {
        int count = 0;
        while (count < SUB_COUNT) {
            int num1 = random.nextInt(NUM_MAX + 1);
            int num2 = random.nextInt(num1 + 1);
            int answer = num1 - num2;
            String coreExpr = num1 + "-" + num2;

            if (!usedExpressions.contains(coreExpr)) {
                usedExpressions.add(coreExpr);
                String fullExpr = String.format("%2d - %2d = %2d", num1, num2, answer);
                allQuestions.add(fullExpr);
                count++;
            }
        }
    }

    /**
     * 按每行3道题排版输出习题
     */
    private static void printQuestions() {
        StringBuilder lineBuilder = new StringBuilder();
        for (int i = 0; i < allQuestions.size(); i++) {
            String questionWithIndex = String.format("%2d. %s", (i + 1), allQuestions.get(i));
            lineBuilder.append(String.format("%-32s", questionWithIndex));

            if ((i + 1) % QUESTIONS_PER_LINE == 0) {
                System.out.println(lineBuilder.toString().trim());
                lineBuilder.setLength(0);
            }
        }
        if (lineBuilder.length() > 0) {
            System.out.println(lineBuilder.toString().trim());
        }
    }

    // ======================== 内置自动化测试函数 ========================
    /**
     * 执行所有测试用例，返回整体测试结果
     */
    private static boolean runAllTests() {
        boolean isAllPassed = true;

        // 1. 测试总题数
        isAllPassed &= testTotalQuestions();
        // 2. 测试无重复算式
        isAllPassed &= testNoDuplicateExpressions();
        // 3. 测试加减法比例
        isAllPassed &= testAddSubRatio();
        // 4. 测试加法合规性（和≤100 + 答案正确）
        isAllPassed &= testAddValidity();
        // 5. 测试减法合规性（差≥0 + 答案正确）
        isAllPassed &= testSubValidity();

        return isAllPassed;
    }

    /**
     * 测试1：总题数是否为TOTAL_QUESTIONS
     */
    private static boolean testTotalQuestions() {
        boolean passed = allQuestions.size() == TOTAL_QUESTIONS;
        String result = passed ? "✅ 通过" : "❌ 失败";
        System.out.printf("[测试1-总题数] 预期：%d道，实际：%d道 → %s%n",
                TOTAL_QUESTIONS, allQuestions.size(), result);
        return passed;
    }

    /**
     * 测试2：是否无重复算式（核心算式Set大小=总题数）
     */
    private static boolean testNoDuplicateExpressions() {
        boolean passed = usedExpressions.size() == TOTAL_QUESTIONS;
        String result = passed ? "✅ 通过" : "❌ 失败";
        System.out.printf("[测试2-无重复] 预期：无重复，实际重复数：%d道 → %s%n",
                TOTAL_QUESTIONS - usedExpressions.size(), result);
        return passed;
    }

    /**
     * 测试3：加减法比例是否符合配置（允许±1误差）
     */
    private static boolean testAddSubRatio() {
        // 统计实际加法/减法题数
        long actualAddCount = allQuestions.stream().filter(expr -> expr.contains("+")).count();
        long actualSubCount = allQuestions.size() - actualAddCount;

        // 允许±1的误差（因整数取整）
        boolean addPassed = Math.abs(actualAddCount - ADD_COUNT) <= 1;
        boolean subPassed = Math.abs(actualSubCount - SUB_COUNT) <= 1;
        boolean passed = addPassed && subPassed;

        String result = passed ? "✅ 通过" : "❌ 失败";
        System.out.printf("[测试3-加减法比例] 预期：加法%d道/减法%d道，实际：加法%d道/减法%d道 → %s%n",
                ADD_COUNT, SUB_COUNT, actualAddCount, actualSubCount, result);
        return passed;
    }

    /**
     * 测试4：加法算式合规性（和≤100 + 答案正确）
     */
    private static boolean testAddValidity() {
        Pattern addPattern = Pattern.compile("(\\d+)\\s+\\+\\s+(\\d+)\\s+=\\s+(\\d+)");
        int errorCount = 0;

        for (String expr : allQuestions) {
            if (expr.contains("+")) {
                Matcher matcher = addPattern.matcher(expr);
                if (matcher.find()) {
                    int num1 = Integer.parseInt(matcher.group(1));
                    int num2 = Integer.parseInt(matcher.group(2));
                    int actualAnswer = Integer.parseInt(matcher.group(3));
                    int expectedAnswer = num1 + num2;

                    // 检查和≤100 + 答案正确
                    if (expectedAnswer > SUM_UPPER_LIMIT || actualAnswer != expectedAnswer) {
                        errorCount++;
                        System.out.printf("  错误加法算式：%s → 预期和≤%d且答案=%d%n",
                                expr, SUM_UPPER_LIMIT, expectedAnswer);
                    }
                }
            }
        }

        boolean passed = errorCount == 0;
        String result = passed ? "✅ 通过" : "❌ 失败";
        System.out.printf("[测试4-加法合规性] 错误算式数：%d道 → %s%n", errorCount, result);
        return passed;
    }

    /**
     * 测试5：减法算式合规性（差≥0 + 答案正确）
     */
    private static boolean testSubValidity() {
        Pattern subPattern = Pattern.compile("(\\d+)\\s+-\\s+(\\d+)\\s+=\\s+(\\d+)");
        int errorCount = 0;

        for (String expr : allQuestions) {
            if (expr.contains("-")) {
                Matcher matcher = subPattern.matcher(expr);
                if (matcher.find()) {
                    int num1 = Integer.parseInt(matcher.group(1));
                    int num2 = Integer.parseInt(matcher.group(2));
                    int actualAnswer = Integer.parseInt(matcher.group(3));
                    int expectedAnswer = num1 - num2;

                    // 检查差≥0 + 答案正确
                    if (expectedAnswer < DIFF_LOWER_LIMIT || actualAnswer != expectedAnswer) {
                        errorCount++;
                        System.out.printf("  错误减法算式：%s → 预期差≥%d且答案=%d%n",
                                expr, DIFF_LOWER_LIMIT, expectedAnswer);
                    }
                }
            }
        }

        boolean passed = errorCount == 0;
        String result = passed ? "✅ 通过" : "❌ 失败";
        System.out.printf("[测试5-减法合规性] 错误算式数：%d道 → %s%n", errorCount, result);
        return passed;
    }
}